# -*- coding:utf-8 -*-
#测试pr
import pygame
import sys
import random

# 全局定义
SCREEN_X = 720
SCREEN_Y = 720
seasonsBg = ["spr.jpg", "sum.jpg", "aut.jpg", "win.jpg"]
seasons = ["春", "夏", "秋", "冬"]
foodTypes = ["food_pumpkin.png","food_fire.png","food_gold.png","food_wind.png","food_thunder.png","food_snow.png"]
speedBak = [0,0]

#玩法介绍
#贪吃蛇的属性值 SATIETY HYDRATION SAN SPEED
    #SATIETY 饱食度 每过一定时间饱食度-1（所以移速快也有一定好处）
    #HYDRATION 渴润度 过低会导致移速降低
    #SAN 精神值 会在其他属性较低时狂降 过低时会影响玩家控制蛇的前进方向
    #SPEED 移动速度，过快或过慢都会导致精神值降低
    #总之，试图保持各项数值在高位吧
#食物种类:
    #目前有六种食物 0-恶魔南瓜 1-火 2-金  3-风 4-雷 5-雪 .
    #每种食物有不同的buff和debuff（四个值，每种食物特别增强其中两项，减少其中一项），具体而言：
        # 0-增加渴润度/饱食度 减SAN 1-增加速度/饱食度 减渴润度 2-增加饱食度/san值 减速度
        # 3-增加渴润度/速度 减SAN 4-增加SAN值/速度 减渴润度 5-增加渴润度/SAN 减速度
    #每次会刷新两种食物，吃掉其中一个之后两种食物都会重新刷新

#季节影响：
    #春夏秋冬四季会造成不同的影响，每过90天就会进入下一个季节
    #春：移速只能单向增加  夏：需要更多水 秋：需要更多食物 冬：既需要涨SAN值又需要增加渴润度

#得分：
    #只有吃到食物才会得分，尝试去吃更多食物吧，不然会随时间饿死的哦
    #撞到墙，咬到自己，或者属性值过低都会导致游戏结束

# 蛇类
# 点以25为单位
class Snake(object):
    # 初始化各种需要的属性 [开始时默认向右/身体块x5]

    def __init__(self):
        self.dirction = pygame.K_RIGHT
        self.body = []
        for x in range(5):
            self.addnode()
        
    # 无论何时 都在前端增加蛇块
    def addnode(self):
        left,top = (0,0)
        if self.body:
            left,top = (self.body[0].left,self.body[0].top)
        node = pygame.Rect(left,top,25,25)#获取头部的位置
        if self.dirction == pygame.K_LEFT:
            node.left -= 25
        elif self.dirction == pygame.K_RIGHT:
            node.left += 25
        elif self.dirction == pygame.K_UP:
            node.top -= 25
        elif self.dirction == pygame.K_DOWN:
            node.top += 25
        self.body.insert(0,node)#根据当前前进方向计算头部的下一个位置
        
    # 删除最后一个块
    def delnode(self):
        self.body.pop()
        
    # 死亡判断
    def isdead(self,properties):
        reason = ""
        # 撞墙
        if self.body[0].x  not in range(SCREEN_X):
            reason = "撞到墙了!"
        if self.body[0].y  not in range(SCREEN_Y):
            reason = "撞到墙了!"
        if self.body[0] in self.body[1:]:
            reason = "咬到自己了!"
        # 某项值不达标
        if properties["渴润度"] <= 0:
            reason = "干死了!"
        if properties["饱食度"] <= 0:
            reason = "饿死了!"
        if properties["精神值"] <= 0:
            reason = "吓死了!"
        if properties["速度"] <= 0:
            reason = "冻死了!"

        return True if reason!="" else False,reason
        
    # 移动！
    def move(self):
        self.addnode()
        self.delnode()
        
    # 改变方向 但是左右、上下不能被逆向改变
    def changedirection(self,curkey,properties):
        LR = [pygame.K_LEFT,pygame.K_RIGHT]
        UD = [pygame.K_UP,pygame.K_DOWN]
        if curkey in LR+UD:
            if (curkey in LR) and (self.dirction in LR):
                return
            if (curkey in UD) and (self.dirction in UD):
                return
            #SAN值过低会影响操控
            if properties["精神值"] < 30:
                if curkey in LR:
                    curkey = random.choice(LR)
                if curkey in UD:
                    curkey = random.choice(UD)
            self.dirction = curkey
       
    #  食物特效
    def foodEffect(self,index,properties,foodType):
        foodIndex = foodTypes.index(foodType[index])
        properties["饱食度"] += 15
        # 0-增加水润度/饱食度 减SAN 1-增加速度/饱食度 减渴润度 2-增加饱食度/san值 减速度 3-增加水润度/速度 减SAN 4-增加SAN值/速度 减水润度 5-增加水润度/SAN 减速度
        # 0-南瓜 1-火 2-金  3-风 4-雷 5-雪
        if foodIndex == 0:#南瓜
            properties["饱食度"] += 10
            properties["渴润度"] += 10
            properties["精神值"] -= 10
        elif foodIndex == 1:#火
            properties["饱食度"] += 10
            properties["速度"] += 2
            properties["渴润度"] -= 10
        elif foodIndex == 2:#金
            properties["饱食度"] += 10
            properties["精神值"] += 10
            properties["速度"] -= 2
        elif foodIndex == 3:#风
            properties["渴润度"] += 10
            properties["速度"] += 2
            properties["精神值"] -= 10
        elif foodIndex == 4:#雷
            properties["精神值"] += 10
            properties["速度"] += 2
            properties["渴润度"] -= 10
        elif foodIndex == 5:#雪
            properties["精神值"] += 10
            properties["渴润度"] += 10
            properties["速度"] -= 2
    #  季节特效 春：移速只能单向增加  夏：需要更多水 秋：需要更多食物 冬：缺SAN值和水润度
    def seasonEffect(self,properties,curSeason):
        hint = ""
        global speedBak
        if curSeason == 0:
            if speedBak[1] > properties["速度"]:
                properties["速度"] = speedBak[1]
            speedBak[1] = properties["速度"]
            hint = '春天不能减速!'
        elif curSeason == 1:
            properties["渴润度"] -= 1
            hint = '夏天容易干渴!'
        elif curSeason == 2:
            properties["饱食度"] -= 1
            hint = '秋天需要更多食物!'
        elif curSeason == 3:
            properties["精神值"] -= 1
            properties["渴润度"] -= 1
            hint = '冬天干涸又可怖!'

        #其他值过低会导致SAN值下降
        if properties["渴润度"]<50 or properties["饱食度"]<50 or properties["速度"]>17 or properties["速度"]<4:
            properties["精神值"] -= 1
        #渴润值过低会导致速度降低
        if properties["渴润度"]<50:
            properties["速度"] -= 1

        return hint


# 食物类
# 方法： 放置/移除
# 点以25为单位
class Food:
    def __init__(self):
        self.food = []
        self.food.insert(0,pygame.Rect(-25, 0, 25, 25))
        self.food.insert(1,pygame.Rect(-25, 25, 25, 25))
        
    def remove(self):
        self.food[0].left = -25
        self.food[1].left = -25
    
    def set(self):
        for index in range(2):
            if self.food[index].left == -25:
                allpos = []
                # 不靠墙太近 25 ~ SCREEN_X-25 之间
                for pos in range(25,SCREEN_X-25,25):
                    allpos.append(pos)
                self.food[index].left = random.choice(allpos)
                self.food[index].top  = random.choice(allpos)

def show_text(screen, pos, text, color, font_bold = False, font_size = 25, font_italic = False):
    #获取系统字体，并设置文字大小  
    #cur_font = pygame.font.SysFont("宋体", font_size)
    cur_font = pygame.font.Font("font.ttf", font_size)
    #设置是否加粗属性  
    cur_font.set_bold(font_bold)  
    #设置是否斜体属性  
    cur_font.set_italic(font_italic)  
    #设置文字内容  
    text_fmt = cur_font.render(text, 1, color)  
    #绘制文字  
    screen.blit(text_fmt, pos)

     
def main():
    curSeason = 0
    properties = {"饱食度": 100, "渴润度": 100, "精神值": 100, "速度": 7.5}
    fontTypes = [(210,180,140),(255,69,0),(255,165,0)] #颜色渐渐危急
    foodType = [random.choice(foodTypes), random.choice(foodTypes)]
    global speedBak

    # 初始化pygame，为使用硬件做准备
    pygame.init()
    pygame.mixer.init()
    screen_size = (SCREEN_X,SCREEN_Y)
    # 创建一个窗口
    screen = pygame.display.set_mode(screen_size)
    pygame.display.set_caption('Snake In Seasons')
    eatSound = pygame.mixer.Sound("eat.wav")
    pygame.mixer.music.load("normal.mp3")
    pygame.mixer.music.play()

    clock = pygame.time.Clock()
    scores = 0
    isdead = False
    timeCnt = 0
    curDay  = 0
    preDay  = 0
    hint = ''
    speedBak = [properties["速度"], properties["速度"]]

    # 蛇/食物
    snake = Snake()
    newFood = Food()
    
    while True:
        for event in pygame.event.get():
            #处理退出事件
            if event.type == pygame.QUIT:
                sys.exit()
            #处理按键事件
            if event.type == pygame.KEYDOWN:
                snake.changedirection(event.key,properties)
                # 死后按space重新
                if event.key == pygame.K_SPACE and isdead:
                    properties = {"饱食度": 100, "渴润度": 100, "精神值": 100, "速度": 7.5}
                    curSeason = 0
                    speedBak = [properties["速度"],properties["速度"]]
                    return main()
                
        #更新背景
        background = pygame.image.load(seasonsBg[curSeason])
        screen.blit(background, (0, 0))

        # 处理蛇的变化
        if not isdead:
            snake.move()
            # 计时
            if speedBak[0] != properties["速度"] or int(timeCnt / properties["速度"]) > 0:
                print(speedBak[0],properties["速度"])
                #速度变化或累计满一天了  天数就+1 并重置计数器
                curDay += 1
                timeCnt = 0 #速度变化后天数+1并重新计数
                speedBak[0] = properties["速度"]
            timeCnt += 1
            if curDay != preDay:
                hint = snake.seasonEffect(properties,curSeason)
                properties["饱食度"] -= 1
                if ((curDay % 9) == 0) and (curDay != 0):
                    curSeason += 1
                    curSeason = int( curSeason % 4 )
                    print("curSeason:"+str(curSeason))
            preDay = curDay

        # 画蛇
        for rect in snake.body:
            pygame.draw.rect(screen,(130,220,170),rect,0)
        pygame.draw.circle(screen, (150, 20, 150), (snake.body[0].left+10,snake.body[0].top+10),8, 0)

        # 显示结束原因
        lastMsg = snake.isdead(properties)
        isdead = lastMsg[0]
        if isdead:
            show_text(screen,(100,200),'游戏结束!'+str(lastMsg[1]),(227,29,18),False,50)
            show_text(screen,(150,260),'press space to try again...',(0,0,22),False,30)
            
        # 吃掉食物处理
        if newFood.food[0] == snake.body[0] or newFood.food[1] == snake.body[0]:
            eatSound.play()
            index = 0 if newFood.food[0] == snake.body[0] else 1
            scores += 50
            newFood.remove()
            snake.addnode()
            snake.foodEffect(index,properties,foodType)
            foodType[0] = random.choice(foodTypes)
            foodType[1] = random.choice(foodTypes)

        # 食物投递
        newFood.set()
        food_img0 = pygame.image.load(foodType[0])
        food_img1 = pygame.image.load(foodType[1])
        screen.blit(food_img0, newFood.food[0])
        screen.blit(food_img1, newFood.food[1])

        # 显示面板信息
        show_text(screen, (10, 10), '第' + str(curDay) + "天|" + seasons[curSeason], (255,78,30), False, 30)
        show_text(screen, (10, 45), hint, (247, 207, 78),False,20)
        show_text(screen, (30, 500), 'Scores: ' + str(scores), (247, 157, 78))
        show_text(screen, (30, 540), '饱食度: ' + str(properties["饱食度"] ), fontTypes[1] if(properties["饱食度"]<50) else fontTypes[2])
        show_text(screen, (200, 540), '渴润度: ' + str(properties["渴润度"] ), fontTypes[1] if(properties["渴润度"]<50) else fontTypes[2])
        show_text(screen, (30, 570), '精神值: ' + str(properties["精神值"] ), fontTypes[1] if(properties["精神值"]<50) else fontTypes[2])
        show_text(screen, (200, 570), '速度: ' + str(properties["速度"]), fontTypes[1] if(properties["速度"]<4 or properties["速度"]>14) else fontTypes[2])
        
        pygame.display.update()
        clock.tick(properties["速度"])
    
    
if __name__ == '__main__':
    main()
